🎖️GitЯра🎖️
Node / meshtastic / Meshtastic-Android / files / androidApp / src / main / kotlin / org / meshtastic / app / MeshUtilApplication.kt
Displaying Raw • Download
androidApp/src/main/kotlin/org/meshtastic/app/MeshUtilApplication.kt 2d20cd8a4708e2ef66e98d5259f3a97ec93f240a (2d20cd8a) Text, 7.30 KB
T8b949e/*
* Copyright (c) 2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Tff7b72package T7ee787org.meshtastic.app
Tff7b72import T7ee787android.app.Application
Tff7b72import T7ee787android.appwidget.AppWidgetProviderInfo
Tff7b72import T7ee787android.content.Context
Tff7b72import T7ee787android.os.Build
Tff7b72import T7ee787androidx.collection.intSetOf
Tff7b72import T7ee787androidx.glance.appwidget.GlanceAppWidgetManager
Tff7b72import T7ee787androidx.work.Configuration
Tff7b72import T7ee787androidx.work.ExistingPeriodicWorkPolicy
Tff7b72import T7ee787androidx.work.PeriodicWorkRequestBuilder
Tff7b72import T7ee787androidx.work.WorkManager
Tff7b72import T7ee787co.touchlab.kermit.Logger
Tff7b72import T7ee787co.touchlab.kermit.Severity
Tff7b72import T7ee787coil3.ImageLoader
Tff7b72import T7ee787coil3.SingletonImageLoader
Tff7b72import T7ee787kotlinx.coroutines.CoroutineScope
Tff7b72import T7ee787kotlinx.coroutines.Dispatchers
Tff7b72import T7ee787kotlinx.coroutines.SupervisorJob
Tff7b72import T7ee787kotlinx.coroutines.TimeoutCancellationException
Tff7b72import T7ee787kotlinx.coroutines.cancel
Tff7b72import T7ee787kotlinx.coroutines.flow.first
Tff7b72import T7ee787kotlinx.coroutines.launch
Tff7b72import T7ee787kotlinx.coroutines.runBlocking
Tff7b72import T7ee787kotlinx.coroutines.withTimeout
Tff7b72import T7ee787org.koin.android.ext.android.get
Tff7b72import T7ee787org.koin.android.ext.koin.androidContext
Tff7b72import T7ee787org.koin.androidx.workmanager.koin.workManagerFactory
Tff7b72import T7ee787org.koin.plugin.module.dsl.startKoin
Tff7b72import T7ee787org.meshtastic.app.di.AndroidKoinApp
Tff7b72import T7ee787org.meshtastic.core.common.ContextServices
Tff7b72import T7ee787org.meshtastic.core.database.DatabaseManager
Tff7b72import T7ee787org.meshtastic.core.repository.MeshPrefs
Tff7b72import T7ee787org.meshtastic.core.repository.ServiceRepository
Tff7b72import T7ee787org.meshtastic.core.resources.Res
Tff7b72import T7ee787org.meshtastic.core.resources.discovery_interrupted_scan_restored
Tff7b72import T7ee787org.meshtastic.core.resources.getStringSuspend
Tff7b72import T7ee787org.meshtastic.core.service.worker.MeshLogCleanupWorker
Tff7b72import T7ee787org.meshtastic.feature.discovery.DiscoveryScanEngine
Tff7b72import T7ee787org.meshtastic.feature.widget.LocalStatsWidgetReceiver
Tff7b72import T7ee787kotlin.time.Duration.Companion.hours
Tff7b72import T7ee787kotlin.time.Duration.Companion.seconds
Tff7b72import T7ee787kotlin.time.toJavaDuration
T8b949e/**
* The main application class for Meshtastic.
*
* This class initializes core application components using Koin for dependency injection.
*/
Tff7b72open Tff7b72class T56d364MeshUtilApplication Tb4b4b4:
Te6edf3ApplicationTb4b4b4(Tb4b4b4)Tb4b4b4,
Te6edf3ConfigurationTb4b4b4.Te6edf3ProviderTb4b4b4,
Te6edf3SingletonImageLoaderTb4b4b4.Te6edf3Factory Tb4b4b4{
Tff7b72private Tff7b72val Te6edf3applicationScope Tff7b72= Te6edf3CoroutineScopeTb4b4b4(Te6edf3SupervisorJobTb4b4b4(Tb4b4b4) Tff7b72+ Te6edf3DispatchersTb4b4b4.Te6edf3DefaultTb4b4b4)
T8b949e/** Supplies Coil's process-wide loader without retaining an Activity in its singleton factory. */
Tff7b72override Tff7b72fun Td2a8ffnewImageLoaderTb4b4b4(Te6edf3contextTb4b4b4: Te6edf3ContextTb4b4b4)Tb4b4b4: Te6edf3ImageLoader Tff7b72= Tff7b72getTff7b72<Te6edf3ImageLoaderTff7b72>Tb4b4b4(Tb4b4b4)
Tff7b72override Tff7b72fun Td2a8ffonCreateTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72superTb4b4b4.Te6edf3onCreateTb4b4b4(Tb4b4b4)
Te6edf3ContextServicesTb4b4b4.Te6edf3app Tff7b72= Tff7b72this
Te6edf3configureFlavorApplicationTb4b4b4(Te6edf3BuildConfigTb4b4b4.Te6edf3APPLICATION_IDTb4b4b4)
Te6edf3startKoinTff7b72<Te6edf3AndroidKoinAppTff7b72> Tb4b4b4{
Te6edf3androidContextTb4b4b4(Tff7b72thisTf0883e@MeshUtilApplicationTb4b4b4)
Te6edf3workManagerFactoryTb4b4b4(Tb4b4b4)
Tb4b4b4}
T8b949e// Schedule periodic MeshLog cleanup
Te6edf3scheduleMeshLogCleanupTb4b4b4(Tb4b4b4)
T8b949e// Generate and publish widget preview for Android 15+ widget picker
Tff7b72if Tb4b4b4(Te6edf3BuildTb4b4b4.Te6edf3VERSIONTb4b4b4.Te6edf3SDK_INT Tff7b72>Tff7b72= Te6edf3BuildTb4b4b4.Te6edf3VERSION_CODESTb4b4b4.Te6edf3VANILLA_ICE_CREAMTb4b4b4) Tb4b4b4{
Te6edf3applicationScopeTb4b4b4.Te6edf3launch Tb4b4b4{
Tff7b72suspend Tff7b72fun Td2a8ffpushPreviewTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72try Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3i Tb4b4b4{ Ta5d6ff"Ta5d6ffPushing generated widget preview...Ta5d6ff" Tb4b4b4}
Tff7b72val Te6edf3result Tff7b72=
Te6edf3GlanceAppWidgetManagerTb4b4b4(Tff7b72thisTf0883e@MeshUtilApplicationTb4b4b4)
Tb4b4b4.Te6edf3setWidgetPreviewsTb4b4b4(
Te6edf3LocalStatsWidgetReceiverTff7b72::Te6edf3classTb4b4b4,
Te6edf3intSetOfTb4b4b4(Te6edf3AppWidgetProviderInfoTb4b4b4.Te6edf3WIDGET_CATEGORY_HOME_SCREENTb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3LoggerTb4b4b4.Te6edf3i Tb4b4b4{ Ta5d6ff"Ta5d6ffsetWidgetPreviews result: Tffd700$Te6edf3resultTa5d6ff" Tb4b4b4}
Tb4b4b4} Tff7b72catch Tb4b4b4(Tf0883e@SuppressTb4b4b4(Ta5d6ff"Ta5d6ffTooGenericExceptionCaughtTa5d6ff"Tb4b4b4) Te6edf3eTb4b4b4: Te6edf3ExceptionTb4b4b4) Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3eTb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Ta5d6ff"Ta5d6ffFailed to set widget previewTa5d6ff" Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Te6edf3pushPreviewTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3widgetStateProviderTb4b4b4: Te6edf3orgTb4b4b4.Te6edf3meshtasticTb4b4b4.Te6edf3featureTb4b4b4.Te6edf3widgetTb4b4b4.Te6edf3LocalStatsWidgetStateProvider Tff7b72= Tff7b72getTb4b4b4(Tb4b4b4)
Tff7b72try Tb4b4b4{
T8b949e// Wait for real data for up to 30 seconds before pushing an updated preview
Te6edf3withTimeoutTb4b4b4(T79c0ff3T79c0ff0.Te6edf3secondsTb4b4b4) Tb4b4b4{
Te6edf3widgetStateProviderTb4b4b4.Te6edf3stateTb4b4b4.Te6edf3first Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3showContent Tff7b72&Tff7b72& Tffa657itTb4b4b4.Te6edf3nodeShortName Tff7b72!Tff7b72= Tff7b72null Tb4b4b4}
Tb4b4b4}
Te6edf3LoggerTb4b4b4.Te6edf3i Tb4b4b4{ Ta5d6ff"Ta5d6ffReal node data acquired. Pushing updated widget preview.Ta5d6ff" Tb4b4b4}
Te6edf3pushPreviewTb4b4b4(Tb4b4b4)
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3eTb4b4b4: Te6edf3TimeoutCancellationExceptionTb4b4b4) Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3iTb4b4b4(Te6edf3eTb4b4b4) Tb4b4b4{ Ta5d6ff"Ta5d6ffTimed out waiting for real node data for widget preview.Ta5d6ff" Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
T8b949e// Initialize DatabaseManager asynchronously with current device address so DAO consumers have an active DB
Te6edf3applicationScopeTb4b4b4.Te6edf3launch Tb4b4b4{
Tff7b72val Te6edf3dbManagerTb4b4b4: Te6edf3DatabaseManager Tff7b72= Tff7b72getTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3meshPrefsTb4b4b4: Te6edf3MeshPrefs Tff7b72= Tff7b72getTb4b4b4(Tb4b4b4)
Te6edf3dbManagerTb4b4b4.Te6edf3initTb4b4b4(Te6edf3meshPrefsTb4b4b4.Te6edf3deviceAddressTb4b4b4.Te6edf3valueTb4b4b4)
Tb4b4b4}
T8b949e// Restore a radio left detuned by a discovery scan that was interrupted (crash, BLE loss, process death)
T8b949e// before it could restore the home LoRa config itself. Never returns; watches reconnects for the app's life.
T8b949e// The engine stays UI-free — we localize the "restored" notice here and push it through the app-wide alert.
Te6edf3applicationScopeTb4b4b4.Te6edf3launch Tb4b4b4{
Tff7b72val Te6edf3scanEngineTb4b4b4: Te6edf3DiscoveryScanEngine Tff7b72= Tff7b72getTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3serviceRepositoryTb4b4b4: Te6edf3ServiceRepository Tff7b72= Tff7b72getTb4b4b4(Tb4b4b4)
Te6edf3scanEngineTb4b4b4.Te6edf3restoreInterruptedSessionsOnReconnect Tb4b4b4{ Te6edf3homePreset Tff7b72-Tff7b72>
Te6edf3serviceRepositoryTb4b4b4.Te6edf3setErrorMessageTb4b4b4(
Te6edf3getStringSuspendTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3discovery_interrupted_scan_restoredTb4b4b4, Te6edf3homePresetTb4b4b4)Tb4b4b4,
Te6edf3SeverityTb4b4b4.Te6edf3WarnTb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffonTerminateTb4b4b4(Tb4b4b4) Tb4b4b4{
T8b949e// Shutdown managers (useful for Robolectric tests).
T8b949e// Non-blocking: cancelAndJoin inside runBlocking on the main thread can deadlock
T8b949e// if any active coroutine is dispatching to Dispatchers.Main.
Te6edf3applicationScopeTb4b4b4.Te6edf3cancelTb4b4b4(Tb4b4b4)
Tff7b72try Tb4b4b4{
Te6edf3runBlocking Tb4b4b4{ Tff7b72getTff7b72<Te6edf3DatabaseManagerTff7b72>Tb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3closeTb4b4b4(Tb4b4b4) Tb4b4b4}
Tb4b4b4} Tff7b72finally Tb4b4b4{
Tff7b72superTb4b4b4.Te6edf3onTerminateTb4b4b4(Tb4b4b4)
Te6edf3orgTb4b4b4.Te6edf3koinTb4b4b4.Te6edf3coreTb4b4b4.Te6edf3contextTb4b4b4.Te6edf3stopKoinTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffscheduleMeshLogCleanupTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3cleanupRequest Tff7b72=
Te6edf3PeriodicWorkRequestBuilderTff7b72<Te6edf3MeshLogCleanupWorkerTff7b72>Tb4b4b4(Te6edf3repeatInterval Tff7b72= T79c0ff1.Te6edf3hoursTb4b4b4.Te6edf3toJavaDurationTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)
Te6edf3WorkManagerTb4b4b4.Te6edf3getInstanceTb4b4b4(Tff7b72thisTb4b4b4)
Tb4b4b4.Te6edf3enqueueUniquePeriodicWorkTb4b4b4(
Te6edf3MeshLogCleanupWorkerTb4b4b4.Te6edf3WORK_NAMETb4b4b4,
Te6edf3ExistingPeriodicWorkPolicyTb4b4b4.Te6edf3UPDATETb4b4b4,
Te6edf3cleanupRequestTb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tff7b72override Tff7b72val Te6edf3workManagerConfigurationTb4b4b4: Te6edf3Configuration
Tff7b72getTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3ConfigurationTb4b4b4.Te6edf3BuilderTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3setWorkerFactoryTb4b4b4(Tff7b72getTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)
Tb4b4b4}
Served by rngit 1.5.0 - Generated in 0.05s